using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using Azure.Web.Configuration;
using Azure.Web.Controllers;

using Microsoft.WindowsAzure;
using StructureMap.Configuration.DSL;
using Xunit;
using Xunit.Extensions;

namespace Azure.Tests.Web
{
    public class ContainerFacts
    {
        public ContainerFacts()
        {
            Container.Reset();
        }

        [Fact]
        public void RunAsRegistersByGeneric()
        {
            var container = Container.RunAs<FakeInitializer>();
            
            var foo = container.GetInstance<IFoo>();

            Assert.NotNull(foo);
        }

        [Theory]
        [ControllersData]
        public void StubInitializerRegistersStubs(Type controllerType)
        {
            var container = Container.RunAs<Stub>();

            var controller = container.GetInstance(controllerType);

            Assert.NotNull(controller);

            Container.Reset();
        }

        [Theory]
        [ControllersData]
        public void AzureInitializerWorks(Type controllerType)
        {
            HackAzureConfiguration();

            var container = Container.RunAs<Cloud>();

            var controller = container.GetInstance(controllerType);

            Assert.NotNull(controller);
            
            Container.Reset();
        }

        public class ControllersDataAttribute : DataAttribute
        {
            public override IEnumerable<object[]> GetData(MethodInfo methodUnderTest, Type[] parameterTypes)
            {
                var controllers = from t in typeof(BlogController).Assembly.GetTypes()
                                  where t.BaseType == typeof(BaseController)
                                  select new object[] { t };

                return controllers;
            }
        }

        private static void HackAzureConfiguration()
        {
            var settings = new Dictionary<string, string>
                               {
                                   {"DataConnectionString", "UseDevelopmentStorage=true"},
                                   {"DiagnosticsConnectionString", "UseDevelopmentStorage=true"}
                               };
            CloudStorageAccount.SetConfigurationSettingPublisher((configName, configSetter) => configSetter(settings[configName]));
        }
    }

    public class FakeInitializer : Registry
    {
        public FakeInitializer()
        {
            For<IFoo>()
                .Use<Bar>();
        }
    }

    public interface IFoo { }
    public class Bar : IFoo { }
}